#!/usr/bin/env python
# coding=utf-8

import importlib
import json
import os
import sys
import seccheck_log
import constant as const
import utils
import aes_cbc
import check

"""
    secchecksuite/pluginfactory.py
    pluginfactory.py for plugintype script or executalbe
    :CopyRight(c) 2019 Inspur Electronic Information Industry Co.,Ltd
"""
sys.path.append(const.COMMON_PATH)


class PluginType(object):
    """
    plugin type , script or executable
    Attributes:
        None
    """

    def __init__(self, key=None):
        self.key = key

    def get_plugin_type(self):
        pass

    def set_plugin_type(self):
        pass

    def start(self, plugin_info):
        pass


class ExePlugin(PluginType):
    """
    plugin type , executable
    Attributes:
        None
    """

    def get_plugin_type(self):
        return "executable"

    def start(self, plugin_info):
        """start execute plugins
            Args:
                plugin_info: plugin_info stored in sqlite database
            Returns:
            Raises:
                BaseException:  An error occurred cleanup a table
         """
        if not check.check_not_none_dict(plugin_info):
            return None
        paras_list = plugin_info.get('plugin_config', None)
        try:
            time_out = int(plugin_info.get('plugin_timeout', const.TIMEOUT))
        except Exception as err:
            time_out = const.TIMEOUT
            seccheck_log.sec_check_logger.error(
                'timeout plugin config is not an interger: {}'.format(err))
        script_path_name = plugin_info.get('plugin_exe', None)
        seccheck_log.sec_check_logger.info('when execute, {} start run'.format(script_path_name))
        TimeOutObj = utils.TimeOut(paras_list, time_out, plugin_info)
        outs_dict = TimeOutObj.run_command_with_time_out()
        return outs_dict

    def get_plugin_info(self, plugin_info):
        """start execute plugins
            Args:
                plugin_info: plugin_info stored in sqlite database
            Returns:
            Raises:
                BaseException:  An error occurred cleanup a table
         """
        if not check.check_not_none_dict(plugin_info):
            return None
        plugin_config = plugin_info.get('plugin_config', None)
        try:
            time_out = int(plugin_info.get('plugin_timeout', const.TIMEOUT))
        except Exception as err:
            time_out = const.TIMEOUT
            seccheck_log.sec_check_logger.error(
                'timeout plugin config is not an interger: {}'.format(err))
        script_path_name = plugin_info['plugin_exe']
        seccheck_log.sec_check_logger.info('when get plugin info, {} start run'.format(script_path_name))
        TimeOutObj = utils.TimeOut(plugin_config, time_out, plugin_info, False)
        outs_dict = TimeOutObj.run_command_with_time_out()
        return outs_dict


class ScriptPlugin(PluginType):
    """
    plugin type , script
    Attributes:
        None
    """

    def get_plugin_type(self):
        return "script"

    def get_plugin_config(self, plugin_info):
        """start script plugins
            Args:
                plugin_info: plugin_info stored in sqlite database
            Returns: plugin_config
            Raises:
                Exception:  An error occurred when change 'command' to integer
         """
        if not check.check_not_none_dict(plugin_info):
            return None
        plugin_config = plugin_info.get('plugin_config', None)
        if plugin_config:
            plugin_config = json.loads(plugin_config)
        else:
            plugin_config = {}
        user_info = plugin_info.get('user_info', None)
        if user_info:
            user_info = json.loads(user_info)
        else:
            user_info = {}
        plugin_config['ip'] = user_info.get('ip', None)
        plugin_config['system_user'] = user_info.get('system_user', None)
        plugin_config['system_pwd'] = user_info.get('system_pwd', None)
        plugin_config['config_path'] = plugin_config.get('config_path', None)
        plugin_config['cmd_time'] = plugin_config.get('cmd_time', None)
        is_pwd_encrypt = user_info.get('encryption', None)
        if str(is_pwd_encrypt) == '1' and plugin_config['system_pwd']:
            plugin_config['system_pwd'] = aes_cbc.aes_decrypt(self.key, plugin_config['system_pwd'], out=False)
        try:
            plugin_config['command'] = int(plugin_config.get('command', None))
        except Exception as err:
            plugin_config['command'] = int(0)
            seccheck_log.sec_check_logger.error(
                'command plugin config is not an interger: {}'.format(err))
        return plugin_config

    def start(self, plugin_info):
        """start script plugins
            Args:
                plugin_info: plugin_info stored in sqlite database
            Returns:
            Raises:
                BaseException:  An error occurred cleanup a table
         """
        try:
            script_path_name = plugin_info['plugin_exe']
            file_path, file_name = os.path.split(script_path_name)
            sys.path.append(file_path)
            plugin_name = file_name.strip()[:-3]
            seccheck_log.sec_check_logger.info('when execute, {} start run'.format(script_path_name))
            module_t = importlib.import_module(plugin_name)
            plugin_log_dict = {'setter': seccheck_log.get_logger('seccheck'), 'user': '',
                               'module': plugin_info['plugin_name'],
                               'task': ''}
            module_t.set_plugin_logger(**plugin_log_dict)
            plugin_config = self.get_plugin_config(plugin_info)
            common = importlib.import_module(const.COMMON_NAME)
            cmd_time = plugin_config.get('cmd_time', const.TIMEOUT)
            common.set_cmd_time(cmd_time)
            info = module_t.check(**plugin_config)
            seccheck_log.sec_check_logger.info('when execute, {} stopped run'.format(script_path_name))
            if not info:
                return utils.joint_error_info(plugin_info, 'result is none')
            return info
        except BaseException as e:
            return utils.joint_error_info(plugin_info, e)

    def get_plugin_info(self, plugin_info):
        """get plugin info from selfdevelop script
            Args:
                plugin_info: pluginid stored in sqlite database
            Returns:
                info: plugin_info
            Raises:
                BaseException:  An error occurred cleanup a table
         """
        try:
            script_path_name = plugin_info['plugin_exe']
            filepath, filename = os.path.split(script_path_name)
            sys.path.append(filepath)
            plugin_name = filename.strip()[:-3]
            seccheck_log.sec_check_logger.info('when get plugin info, {} start run'.format(script_path_name))
            module_t = importlib.import_module(plugin_name)
            info = module_t.get_plugin_info()
            seccheck_log.sec_check_logger.info('when get plugin info, {} stopped run'.format(script_path_name))
            return info
        except BaseException as e:
            seccheck_log.sec_check_logger.error('when {} get_plugin_info occur some error:{}'.format(
                plugin_info['plugin_exe'], e))
            return None


class PluginTypeFactory(object):
    """
    plugin type factory ,base class
    Attributes:
        None
    """

    def createPlugin(self):
        pass


class ExePluginType(PluginTypeFactory):
    """
    plugin type , executable
    Attributes:
        None
    """

    def createPlugin(self, key=None):
        return ExePlugin(key)


class ScriptPluginType(PluginTypeFactory):
    """
    plugin type , script
    Attributes:
        None
    """

    def createPlugin(self, key=None):
        return ScriptPlugin(key)
